////////////////////////////////////////////////////////////////////
// Programme d'extraction/réinsertion de scénario pour Chrono Cross
////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////
// Nemesis pour Terminus Traduction (tt_nemesis@yahoo.fr)
// Date de création :		12/09/03
// Dernière modification :	05/02/04
////////////////////////////////////////////////////////////////////

// Entete
#include "Scenar.h"

// Type de la structure d'un bloc
typedef struct {
	unsigned _int16 adr;
	unsigned _int16 larg;
	unsigned _int16 haut;
	unsigned _int16 pix;
} Scn_TBloc;

/*------------------------------------------------------------------
  Chargement de la table de caractères
------------------------------------------------------------------*/
void Scn_Table (char *table, char *inout)
{
	Tbl_Libere();
	if (inout[0]==LECTURE)
		Tbl_Charge(table, TBL_IN);
	else
		Tbl_Charge(table, TBL_OUT);
}

/*------------------------------------------------------------------
  Inscription d'un pointeur dans le texte de sortie
--------------------------------------------------------------------
 <- num : numéro de bloc
 <- bloc : informations sur le bloc
 <- out_f : fichier où l'on écrit les informations
------------------------------------------------------------------*/
void Scn_Code_InEcr (int num,Scn_TBloc bloc,FILE *out_f)
{
	int c;

	fputc('\n',out_f);
	fprintf(out_f,SCN_PTR_INFOS,num,bloc.pix,bloc.haut);
	fputc(SCN_DEB_1,out_f);
	for(c=0;c<bloc.larg;c++)
		fputc(SCN_LIGNE,out_f);
	fputc('\n',out_f);
}

/*------------------------------------------------------------------
  Lecture d'un pointeur dans le scénario
--------------------------------------------------------------------
 <- bloc : informations sur le bloc
 <- in_f : fichier où l'on écrit les informations
------------------------------------------------------------------*/
void Scn_Code_InLec (Scn_TBloc *bloc,FILE *in_f)
{
	fread(&(bloc->adr),sizeof(_int16),1,in_f);
	fread(&(bloc->larg),sizeof(_int16),1,in_f);
	fread(&(bloc->haut),sizeof(_int16),1,in_f);
	fread(&(bloc->pix),sizeof(_int16),1,in_f);
}

/*------------------------------------------------------------------
  Copie d'octets en décimal (presque cf "Coordonnees.cpp")
--------------------------------------------------------------------
 <- nb : nombre d'octets à copier (>=1)
 <- in_f : fichier d'entrée
 <- out_f : fichier de sortie
------------------------------------------------------------------*/
void Scn_Copie_10 (int nb, FILE *in_f, FILE *out_f)
{
	int o;
	unsigned _int16 c;

	fputc(SCN_SPEC,out_f);
	for(o=0;o<nb-1;o++) {
		c=fgetc(in_f);
		fprintf(out_f,"%03d.",c);
	}
	c=fgetc(in_f);
	fprintf(out_f,"%03d",c);
	fputc(SCN_SPEC,out_f);
}

/*------------------------------------------------------------------
  Extraction du scénario d'un fichier
--------------------------------------------------------------------
 <- dir : dossier du fichier
 <- fich : numéro de fichier de scénario
------------------------------------------------------------------*/
void Scn_Extraction (char *dir, int fich)
{
	// Blocs de texte
	Scn_TBloc blocs[SCN_BLOCS_NB];
	int blocs_nb;
	// Fichier de textes à décompresser
	FILE *scn_f;
	char scn_nom[SCN_NOM_MAX];
	char *scn_nom2;
	char scn_nom_complet[SCN_NOM_MAX];
	// Fichier de sortie
	FILE *out_f;
	// Nom du dossier
	char dossier[SCN_NOM_MAX];
	// Index des blocs
	int b;
	// Retour de la lecture
	int car;

	// Recherche du fichier de textes
	sprintf(scn_nom,"%04d",fich);
	sprintf(dossier,"%s%s",DIR_FICH_IN,dir);
	Fichier_Cherche(dossier,scn_nom,EXT_SCENAR,&scn_nom2);
	sprintf(scn_nom_complet,"%s%s",dossier,scn_nom2);
	// Ouverture du fichier de textes
	scn_f=fopen(scn_nom_complet,"rb");

	// Fichier existant ?
	if (scn_f==NULL)
		Main_Message_S("Impossible d'ouvrir le scenario %s.\n",dir,ER);
	else {
		// Ouverture du texte extrait
		strcpy(&scn_nom_complet[strlen(scn_nom_complet)-3],EXT_TXT);
		out_f=fopen(scn_nom_complet,"w");
		// Chargement des informations des blocs
		blocs_nb=0;
		do {
			Scn_Code_InLec(&blocs[blocs_nb],scn_f);			
			blocs_nb++;
		} while (blocs_nb*8<blocs[0].adr);
		// Inscription du nombre de pointeurs
		blocs_nb--;
		fprintf(out_f,"%05d",blocs_nb);
		for(b=0;b<blocs_nb;b++) {
			// Inscription du pointeur
			Scn_Code_InEcr(b,blocs[b],out_f);
			// Placement au niveau du texte
			fseek(scn_f,blocs[b].adr,SEEK_SET);
			// Extraction du texte
			fputc(SCN_DEB_A,out_f);
			do {
				car=Tbl_Lecture(scn_f,out_f);
				if (car==R_SAUT)
					fputc(SCN_DEB_A,out_f);
			} while(ftell(scn_f)<blocs[b+1].adr
				&& feof(scn_f)==0);
		}
		// Fermeture des fichiers
		fclose(out_f);
		fclose(scn_f);
	}
}

/*------------------------------------------------------------------
  Appel de extraction pour des textes hors scénario
--------------------------------------------------------------------
 <- fich : dossier|fichir
------------------------------------------------------------------*/
void Scn_Extr_Exec (char* fich) {
	// Dossier/fichier
	char* dossier;
	char* fichier;
	char* table;

	Main_Message_S("Dump du texte %s... ",fich,OK);

	// Décomposition dossier/fichier
	dossier=strtok(fich,SEPARATEUR);
	if (dossier[0]==NEUTRE)
		dossier[0]=0;
	fichier=strtok(NULL,SEPARATEUR);
	table=strtok(NULL,SEPARATEUR);

	// Chargement de la table
	Tbl_Libere();
	Tbl_Charge(table, TBL_IN);
	// Appel de l'extracteur
	Scn_Extraction(dossier,atoi(fichier));

	Main_OK();
}

/*------------------------------------------------------------------
  Test sur une ligne pour déceler un manque de pointeur
--------------------------------------------------------------------
 <- ligne : ligne de texte à tester
------------------------------------------------------------------*/
int Scn_Test_Ligne (char *ligne)
{
	unsigned int c;
	int ptr=ER;

	// Teste les premiers caratères de la ligne
	// par exemple ----- pour vérifier si on n'a
	// pas oublié un pointeur au dessus
	for(c=1;c<strlen(ligne) && c<SCN_PTR_TEST && ptr==ER;c++)
		if (ligne[c]!=SCN_DEB_1)
			ptr=OK;

	return(ptr);
}

/*------------------------------------------------------------------
  Lecture des informations de "fenêtrage" dans le texte
--------------------------------------------------------------------
 <- bloc : informations sur le bloc
 <- in_f : fichier où l'on lit les informations
------------------------------------------------------------------*/
void Scn_Code_OutLec (Scn_TBloc *bloc,FILE *in_f)
{
	_int16 num,pix,haut;
	// Ligne de texte lue
	char ligne[SCN_LIGNE_MAX];

	// Première ligne d'infos générales
	fgets(ligne,SCN_LIGNE_MAX,in_f);

	sscanf(ligne,SCN_PTR_INFOS,&num,&pix,&haut);
	bloc->pix=pix;
	bloc->haut=haut;
	// Deuxième ligne d'info de largeur
	fgets(ligne,SCN_LIGNE_MAX,in_f);
	bloc->larg=strlen(ligne)-2;
	bloc->pix=__max(8*bloc->larg,bloc->pix);
}

/*------------------------------------------------------------------
  Ecriture des informations de "fenêtrage" dans le scénario
--------------------------------------------------------------------
 <- bloc : informations sur le bloc
 <- out_f : fichier où l'on écrit les informations
------------------------------------------------------------------*/
void Scn_Code_OutEcr (Scn_TBloc bloc,FILE *out_f)
{
	fwrite(&(bloc.adr),sizeof(_int16),1,out_f);
	fwrite(&(bloc.larg),sizeof(_int16),1,out_f);
	fwrite(&(bloc.haut),sizeof(_int16),1,out_f);
	fwrite(&(bloc.pix),sizeof(_int16),1,out_f);
}

/*------------------------------------------------------------------
  Réinsertion des textes d'un fichier
--------------------------------------------------------------------
 <- dir : dossier du fichier
 <- fich : numéro de fichier de scénario
------------------------------------------------------------------*/
void Scn_Reinsertion (char *dir, int fich)
{
	// Blocs de texte
	Scn_TBloc blocs[SCN_BLOCS_NB];
	int blocs_nb=-1;
	// Fichier de textes à modifier
	FILE *scn_f;
	char scn_nom[SCN_NOM_MAX];
	char *scn_nom2;
	char scn_nom_complet[SCN_NOM_MAX];
	// Fichier d'entrée
	FILE *in_f;
	// Nom du dossier
	char dossier[SCN_NOM_MAX];
	// Index des fichiers et blocs
	int t;
	// Ligne de texte lue
	char ligne[SCN_LIGNE_MAX];
	// Position dans le fichier texte
	unsigned int pos;
	// Fin de lecture de bloc
	bool fin_bloc;

	// Recherche du fichier de textes
	sprintf(scn_nom,"%04d",fich);
	sprintf(dossier,"%s%s",DIR_FICH_OUT,dir);
	Fichier_Cherche(dossier,scn_nom,EXT_TXT,&scn_nom2);
	sprintf(scn_nom_complet,"%s%s",dossier,scn_nom2);
	// Ouverture du fichier de textes
	in_f=fopen(scn_nom_complet,"r");

	if (strcmp(dir,"D2929\\")==0)
		fich=fich;
	// Fichier existant ?
	if (in_f==NULL)
		Main_Message_S("Impossible d'ouvrir le texte %s.\n",dir,ER);
	else {
		// Ouverture du scénario
		strcpy(&scn_nom_complet[strlen(scn_nom_complet)-3],EXT_SCENAR);
		scn_f=fopen(scn_nom_complet,"wb");
		// Lecture du nombre de blocs
		fgets(ligne,SCN_LIGNE_MAX,in_f);
		sscanf(ligne,"%05d",&blocs_nb);
		// Placement dans le fichier de scenario
		fseek(scn_f,(blocs_nb+1)*8,SEEK_SET);
		// Réinsertion des textes
		for(t=0;Main_Test()==OK && t<blocs_nb;t++) {
			// Lecture le la ligne d'information du pointeur
			Scn_Code_OutLec(&blocs[t],in_f);
			// Récupération de l'adresse
			blocs[t].adr=(_int16)ftell(scn_f);
			// Lecture du texte extrait jusqu'à un pointeur
			pos=ftell(in_f);
			fin_bloc = false;
			do {
				fseek(in_f,pos,SEEK_SET);
				fgets(ligne,SCN_LIGNE_MAX,in_f);
				// Premier caractère parasite
				if (ligne[0]==SCN_DEB_A) {
					// Traitement de la ligne
					Tbl_Ecriture(&ligne[1],scn_f);
					pos=ftell(in_f);
				} else
					fin_bloc = true;
			} while (!feof(in_f) && Main_Test()==OK && !fin_bloc);
			// Affichage en cas d'erreur
			if (Main_Test()!=OK) {
				fgets(ligne,SCN_LIGNE_MAX,in_f);
				Main_Message_S("Fichier : %s.\n",scn_nom_complet,ER);
				Main_Message_D("Position : %d.\n",pos,ER);
				Main_Message_S("Erreur avant : %s.\n",ligne,ER);
			}
			fseek(in_f,pos,SEEK_SET);
		}
		blocs[t].adr=(_int16)ftell(scn_f);
		// Fermeture du texte extrait
		fclose(in_f);
		// Réinsertion des adresses
		fseek(scn_f,0,SEEK_SET);
		for(t=0;t<=blocs_nb;t++)
			Scn_Code_OutEcr(blocs[t],scn_f);
		// Fermeture du fichier des textes
		fclose(scn_f);
	}
}

/*------------------------------------------------------------------
  Appel de la réinsertion pour des textes hors scénario
--------------------------------------------------------------------
 <- fich : dossier|fichier
------------------------------------------------------------------*/
void Scn_Rein_Exec (char* fich) {
	// Dossier/fichier
	char* dossier;
	char* fichier;
	char* table;

	Main_Message_S("Reinsertion du texte %s... ",fich,OK);

	// Décomposition dossier/fichier
	dossier=strtok(fich,SEPARATEUR);
	if (dossier[0]==NEUTRE)
		dossier[0]=0;
	fichier=strtok(NULL,SEPARATEUR);
	table=strtok(NULL,SEPARATEUR);

	// Chargement de la table
	Tbl_Libere();
	Tbl_Charge(table, TBL_IN);
	// Appel de l'extracteur
	Scn_Reinsertion(dossier,atoi(fichier));

	Main_OK();
}

